#pragma once

#include "znx_queue.h"
#include "znx_rwlock.h"
#include "znx_thread_base.h"


typedef struct {
    znx_queue_t                     queue;
    uint64_t                        hash_key;
} znx_hash_node_t;

typedef int (*znx_hash_node_cmp_pt)(znx_hash_node_t *node_a, znx_hash_node_t *node_b);


typedef struct znx_hash_tab_s       znx_hash_tab_t;


typedef struct {
    uint64_t                        slot_num;
    znx_queue_t                     *slots;     // slot array
    uint64_t                        count;
    znx_hash_tab_t                  *tab;
} znx_hash_bucket_t;


struct znx_hash_tab_s {
    uint64_t                        bucket_num;
    znx_hash_bucket_t               *buckets;   // bucket array
    znx_hash_node_cmp_pt            node_cmp;
};


/**
 * total_solts = bucket_num * slots_num.
 * the expansion of the hash table is carried out in units of buckets.
 * reasonable bucket_num can reduce performance problems caused by hash table expansion.
 */
znx_hash_tab_t *
znx_hash_tab_create(uint64_t bucket_num, uint64_t slot_num,
    znx_hash_node_cmp_pt cmp_handler);


/**
 * destory hash tab does not release the internal object.
 */
void
znx_hash_tab_destory(znx_hash_tab_t *tab);


void
znx_hash_tab_add(znx_hash_tab_t *tab, znx_hash_node_t *node);


znx_hash_node_t *
znx_hash_tab_get(znx_hash_tab_t *tab, znx_hash_node_t *target);


znx_hash_node_t *
znx_hash_tab_remove(znx_hash_tab_t *tab, znx_hash_node_t *target);
